<template>
  <div>
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/welcome' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>商品管理</el-breadcrumb-item>
      <el-breadcrumb-item>参数列表</el-breadcrumb-item>
    </el-breadcrumb>
    <el-card>
      <el-alert title="注意：只允许给三级分类添加参数" type="warning" show-icon></el-alert>请选择商品分类：
      <!-- 级联选择器 -->
      <el-cascader
        v-model="selectOptionArr"
        :options="cascaderList"
        :props="cascaderProp"
        @change="cascaderHandleChange"
      ></el-cascader>

      <!-- 标签页 -->
      <el-tabs v-model="activeTab" @tab-click="tabsHandleClick">
        <!-- name设为only和many方便传递给后台 -->
        <el-tab-pane label="动态属性" name="many">
          <el-button
            size="mini"
            type="primary"
            :disabled="isBtnDisabled"
            @click="showAddParamsDialog"
          >添加动态属性</el-button>
          <el-table :data="manyTabList">
            <el-table-column type="expand">
              <!-- 循环生成tag标签 放在模板里 好得到当前一行的数据-->
              <template slot-scope="scope">
                <!-- 循环中的item即为attr_vals这个数组中的每一项 attr_vals本是字符串 是在获取参数请求时转换成数组的-->
                <!--添加 :key="i"高效的更新页面 因为vue底层通过虚拟DOM更新页面 新旧DOM对比 采用deff算法  -->
                <el-tag
                  @close="removeTag(i,scope.row)"
                  closable
                  v-for="(item,i) in scope.row.attr_vals"
                  :key="i"
                >{{item}}</el-tag>
                <!-- 添加新tag -->
                <el-input
                  class="input-new-tag"
                  v-if="scope.row.inputVisible"
                  v-model="scope.row.inputValue"
                  ref="saveTagInput"
                  size="small"
                  @keyup.enter.native="handleInputConfirm(scope.row)"
                  @blur="handleInputConfirm(scope.row)"
                ></el-input>
                <el-button
                  v-else
                  class="button-new-tag"
                  size="small"
                  @click="showInput(scope.row)"
                >+ New Tag</el-button>
              </template>
            </el-table-column>
            <el-table-column type="index"></el-table-column>
            <el-table-column label="参数名称" prop="attr_name"></el-table-column>
            <el-table-column>
              <template slot-scope="scope">
                <el-button
                  type="primary"
                  class="el-icon-edit"
                  @click="showEditParamsDialog(scope.row)"
                >编辑</el-button>
                <el-button type="danger" class="el-icon-delete" @click="removeParams(scope.row)">删除</el-button>
              </template>
            </el-table-column>
          </el-table>
        </el-tab-pane>

        <el-tab-pane label="静态属性" name="only">
          <el-button
            size="mini"
            type="primary"
            :disabled="isBtnDisabled"
            @click="showAddParamsDialog"
          >添加动态属性</el-button>
          <el-table :data="onlyTabList">
            <el-table-column type="expand">
              <!-- 循环生成tag标签 放在模板里 好得到当前一行的数据-->
              <template slot-scope="scope">
                <!-- 循环中的item即为attr_vals这个数组中的每一项 attr_vals本是字符串 是在获取参数请求时转换成数组的-->
                <!--添加 :key="i"高效的更新页面 因为vue底层通过虚拟DOM更新页面 新旧DOM对比 采用deff算法  -->
                <el-tag
                  @close="removeTag(i,scope.row)"
                  closable
                  v-for="(item,i) in scope.row.attr_vals"
                  :key="i"
                >{{item}}</el-tag>
                <!-- 添加新tag -->
                <el-input
                  class="input-new-tag"
                  v-if="scope.row.inputVisible"
                  v-model="scope.row.inputValue"
                  ref="saveTagInput"
                  size="small"
                  @keyup.enter.native="handleInputConfirm(scope.row)"
                  @blur="handleInputConfirm(scope.row)"
                ></el-input>
                <el-button
                  v-else
                  class="button-new-tag"
                  size="small"
                  @click="showInput(scope.row)"
                >+ New Tag</el-button>
              </template>
            </el-table-column>
            <el-table-column type="index"></el-table-column>
            <el-table-column label="参数名称" prop="attr_name"></el-table-column>
            <el-table-column>
              <template slot-scope="scope">
                <el-button
                  type="primary"
                  class="el-icon-edit"
                  @click="showEditParamsDialog(scope.row)"
                >编辑</el-button>
                <el-button type="danger" class="el-icon-delete" @click="removeParams(scope.row)">删除</el-button>
              </template>
            </el-table-column>
          </el-table>
        </el-tab-pane>
      </el-tabs>
    </el-card>

    <!-- 添加静态或动态属性的对话框 -->
    <el-dialog
      @close="addParamsDialogClose"
      :title="activeTab=='many'?'添加动态属性':'添加静态属性'"
      :visible.sync="addParamsDialogVisible"
      width="50%"
    >
      <!-- 对话框中的表单验证 -->
      <el-form
        :model="addParamsForm"
        :rules="addParamsRules"
        ref="addRuleRef"
        label-width="150px"
        class="demo-ruleForm"
      >
        <el-form-item :label="activeTab=='many'?'添加动态属性':'添加静态属性'" prop="attr_name">
          <el-input v-model="addParamsForm.attr_name"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="addParamsDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="addParamsSub">确 定</el-button>
      </span>
    </el-dialog>
    <!-- 编辑参数对话框 -->
    <el-dialog
      @close="editParamsDialogClose"
      :title="activeTab=='many'?'添加动态属性':'添加静态属性'"
      :visible.sync="editParamsDialogVisible"
      width="50%"
    >
      <el-form
        :model="editParamsForm"
        :rules="editParamsRules"
        ref="editRuleRef"
        label-width="150px"
        class="demo-ruleForm"
      >
        <el-form-item :label="activeTab=='many'?'添加动态属性':'添加静态属性'" prop="attr_name">
          <el-input v-model="editParamsForm.attr_name"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="editParamsDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="editParamsSub">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
export default {
  data() {
    return {
      // 用来存储级联选择器渲染出来的所有分类
      cascaderList: [],
      //存储级联选择器中选中的商品id
      selectOptionArr: [],
      cascaderProp: {
        expandTrigger: "hover",
        label: "cat_name",
        value: "cat_id"
      },
      //存储标签页当前显示的页面
      activeTab: "many",
      //分别用来存放 请求返回的静态数据和动态数据
      onlyTabList: [],
      manyTabList: [],

      //   控制是否显示添加静、动态属性的对话框
      addParamsDialogVisible: false,
      addParamsForm: {
        attr_name: ""
      },
      addParamsRules: {
        attr_name: [
          { required: true, message: "请输入参数名称", trigger: "blur" }
        ]
      },

      //   编辑对话框的属性
      editParamsDialogVisible: false,
      editParamsForm: {
        attr_name: ""
      },
      editParamsRules: {
        attr_name: [
          { required: true, message: "请输入参数名称", trigger: "blur" }
        ]
      },
      editId: {}
      // // 是否显示添加新标签的input输入框
      // inputVisible:false,
      // // 双向绑定的input里面的内容
      // inputValue: '',
      // 上面两个作废 在data里面定义 会使每个参数里的添加tag标签公用一个inputVisible 和inputValue 会有连同问题
      //  解决办法就是给每一行参数添加自己的inputVisible 和inputValue 改变也只改变自己的
    };
  },

  methods: {
    //先获取级联选择器中的数据 但这一次需要获取所有分类 在cate.vue中添加分类时 只获取了二级分类
    async getCascaderList() {
      var res = await this.axios.get("categories");
      console.log(res);
      if (res.meta.status == 200) {
        this.cascaderList = res.data;
      }
    },

    cascaderHandleChange() {
      // 选择了某个三级商品分类之后 获取参数
      this.getParams();
    },

    // 切换标签页触发的函数
    tabsHandleClick() {
      //切换标签页 获取参数列表
      this.getParams();
    },

    //将获取商品的参数的代码封装到getParams函数中
    // 因为改变级联选择器时cascaderHandleChange，和切换tabs标签页时tabsHandleClick 都要发送请求获取数据
    async getParams() {
      //如果选择的不是三级分类 就清空选择的数组 结束函数
      if (this.selectOptionArr.length != 3) {
        this.selectOptionArr = [];
        this.manyTabList = [];
        this.onlyTabList = [];

        return;
      }
      //   发送请求 获取相应商品的参数
      var res = await this.axios.get(`categories/${this.cateId}/attributes`, {
        params: {
          sel: this.activeTab
        }
      });
      if (res.meta.status == 200) {
        console.log(res.data);
        // 先循环每一个参数中的attr_vals属性 将其从字符串转换为数组 好循环生成每一个参数展开行里面的tag标签
        res.data.forEach(item => {
          // 如果某一个参数下面没有属性 即attr_vals为一个空字符串 那么split(" ")分割会得到一个数组里面有一项是个空字符串
          // 这样会在页面中渲染出一个空白tag 所以先做个判断 若attr_vals为一个空字符串 就赋值为空数组
          item.attr_vals = item.attr_vals ? item.attr_vals.split(",") : [];
          // 给每一项添加 inputVisible属性 和inputValue属性 添加时就不会影响其他参数
          item.inputVisible = false;
          item.inputValue = "";
        });
        // 获取成功 将得到的数据保存到data中 供以渲染页面 但是怎么判断获取到的是静态参数还是动态参数呢
        // 通过当前的this.activeTab的值
        if (this.activeTab == "only") {
          this.onlyTabList = res.data;
        } else {
          this.manyTabList = res.data;
        }
      }
    },

    // 显示添加属性对话框
    showAddParamsDialog() {
      this.addParamsDialogVisible = true;
    },

    // 点击确定 添加属性
    addParamsSub() {
      // 提交之前先进行表单验证
      this.$refs.addRuleRef.validate(async flag => {
        if (!flag) return;
        // 验证成功发送请求
        var res = await this.axios.post(
          `categories/${this.cateId}/attributes`,
          {
            attr_name: this.addParamsForm.attr_name,
            attr_sel: this.activeTab
          }
        );
        if (res.meta.status == 201) {
          this.$message.success("添加属性成功");
        } else {
          this.$message.error("添加属性失败");
        }
        this.addParamsDialogVisible = false;
        this.getParams();
      });
    },

    // 关闭添加属性对话框时 重置表单
    addParamsDialogClose() {
      this.$refs.addRuleRef.resetFields();
    },

    // 显示编辑对话框
    async showEditParamsDialog(row) {
      this.editParamsDialogVisible = true;
      console.log(row);
      var res = await this.axios.get(
        `categories/${this.cateId}/attributes/${row.attr_id}`,
        {
          params: {
            attr_sel: this.activeTab
          }
        }
      );
      //   console.log(res);
      //   将查询到的数据存储到editParamsForm中
      this.editParamsForm = res.data;
    },

    // 点击确定编辑对话框
    async editParamsSub() {
      console.log(this.editId);

      var res = await this.axios.put(
        `categories/${this.cateId}/attributes/${this.editParamsForm.attr_id} `,
        {
          attr_name: this.editParamsForm.attr_name,
          attr_sel: this.activeTab
        }
      );
      console.log(res);
      if (res.meta.status == 200) {
        this.editParamsDialogVisible = false;
        this.$message.success("更新成功");
        this.getParams();
      } else {
        this.$message.error("更新失败");
      }
    },

    // 关闭编辑对话框触发的事件 重置表单
    editParamsDialogClose() {
      this.$refs.editRuleRef.resetFields();
    },

    // 点击删除按钮 删除对应属性
    removeParams(row) {
      // 需要一个确认删除弹框
      this.$cfm("此操作将永久删除该属性, 是否继续?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(async () => {
          var res = await this.axios.delete(
            `categories/${this.cateId}/attributes/${row.attr_id}`
          );
          if (res.meta.status == 200) {
            this.$message.success("删除成功!");
            this.getParams();
          } else {
            this.$message.error("删除失败!");
          }
        })
        .catch(() => {
          this.$message.info("取消删除");
        });
    },

    // 默认显示添加tag按钮 点击添加时 显示输入框
    showInput(row) {
      row.inputVisible = true;
      //  上一步执行完之后 只是改变了row.inputVisible的值 页面还没刷新 input还没出来没法聚焦
      // element提供了一个$nextTick函数 当页面重新渲染时就会执行里面的回调函数
      this.$nextTick(_ => {
        this.$refs.saveTagInput.$refs.input.focus();
      });
    },

    // 封装编辑Tags的函数
    async editTags(row){
        // 然后发送请求
        // 携带的参数中attr_vals必须为新标签和旧标签一起的字符串
       var res = await this.axios.put(
          `categories/${this.cateId}/attributes/${row.attr_id}`,
          {
            attr_name: row.attr_name,
            attr_sel: this.activeTab,
            attr_vals: row.attr_vals.join(",")
          }
        );
        console.log(res);
        if (res.meta.status == 200) {
          this.$message.success("添加成功");
          row.inputVisible = false;
          row.inputValue = "";
        }
    },

    // 添加新标签时 按回车键或者输入框失去焦点时触发的事件
    handleInputConfirm(row) {
      if (row.inputValue.trim().length == 0) {
        row.inputVisible = false;
        row.inputValue = "";
        this.$message.error("当前输入内容不合法");
        return;
      } else {
        // 发送请求添加新标签
        // 先假更新页面 直接添加到数组中
        row.attr_vals.push(row.inputValue);
      // 发送请求更新数据库里的attr_vals
        this.editTags(row)
        // 不必刷新页面 因为发送请求之前做了假刷新
      }
    },

    // 删除tag标签
    // 参数i为 第几个当前属性行的tag标签 row为当前那一行属性所有的内容
    removeTag(i, row) {
      row.attr_vals.splice(i, 1);
      // 发送请求 更新数据
      this.editTags(row)

    }
  },

  created() {
    this.getCascaderList();
    this.getParams();
  },

  computed: {
    //计算属性判断添加参数按钮是否可用 如果选择的不是三级分类 就禁用按钮
    isBtnDisabled() {
      if (this.selectOptionArr.length == 3) {
        return false;
      } else {
        return true;
      }
    },
    //定义一个计算属性 专门用来获取到 三级分类的id并保存到cateId中 因为常用
    cateId() {
      if (this.selectOptionArr.length == 3) {
        return this.selectOptionArr[2];
      }
    }
  }
};
</script>

<style lang='less' scoped>
.el-alert {
  margin-bottom: 20px;
}
.el-tag {
  margin: 7px;
}
.el-input {
  width: 120px;
}
</style>
